package thinkinjava4.ch21_concurrency;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

class ExplicitPairManager1 extends PairManager {
    private Lock lock = new ReentrantLock();

    /**
     * 我的理解：synchronized 方法相当于 synchronized(this){ //方法所有内容 }
     */
    @Override
    public synchronized void increment() {
        lock.lock();
        try {
            p.incrementX();
            p.incrementY();
            store(getPair());
        } finally {
            lock.unlock();
        }
    }
}

class ExplicitPairManager2 extends PairManager {
    private Lock lock = new ReentrantLock();

    /**
     * getPair的锁和increment的锁必须是同一把锁
     * 书上的示例代码会产生不同的x,y的Pair
     * 原因是虽然父类getPair使用了synchronized,但是synchronized锁和子类ReentrantLock不是同一把锁
     * 导致getPair的时候，increment可以在同时执行，这时x加1，y还没有加1时执行getPair就会出问题
     *
     * @return
     */
    @Override
    public Pair getPair() {
        lock.lock();
        Pair temp;
        try {
            temp = super.getPair();
        } finally {
            lock.unlock();
        }
        return temp;
    }

    @Override
    public void increment() {
        Pair temp;
        lock.lock();
        try {
            p.incrementX();
            p.incrementY();
            temp = getPair();
        } finally {
            lock.unlock();
        }
        store(temp);
    }
}

public class ExplicitCriticalSection {
    public static void main(String[] args) {
        PairManager pman1 = new ExplicitPairManager1();
        PairManager pman2 = new ExplicitPairManager2();
//        PairManager pman3 = new PairManager1();
        CriticalSection.testApproaches(pman1, pman2);
    }
}
